package com.example.shop.fgo.task.download.controller;

import android.text.TextUtils;

import com.example.shop.fgo.Constant;
import com.example.shop.fgo.entity.DownloadUrlEntity;
import com.example.shop.fgo.net.DownloadUrlServe;
import com.example.shop.fgo.task.common.model.TaskState;
import com.example.shop.fgo.task.download.model.DownloadTask;
import com.example.shop.fgo.utils.CookieUtil;
import com.example.shop.fgo.utils.MakeFileHash;
import com.example.shop.fgo.utils.SDUtil;
import com.example.shop.fgo.utils.SizeUtil;
import com.example.shop.library.net.NetJsonUtil;
import com.orhanobut.logger.Logger;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import retrofit2.Call;
import retrofit2.Response;

/**
 * Created by Administrator on 2017/2/21.
 */

public class DownloadThread extends Thread{
    private DownloadTask mDownloadTaskNow;
    private DownloadController mDownloadController;
    public static final Object SYNC=new Object();
    public DownloadThread() {
        mDownloadController = new DownloadController();
    }

    @Override
    public void run() {
        super.run();

        aa: while (true){
            synchronized (SYNC){
                //找等待（排队）的任务
                mDownloadTaskNow=mDownloadController.getDownloadTaskWait();
                //没有下载任务，那么线程就终止了...
                if (mDownloadTaskNow==null) {
                    Logger.e("全部下载完毕  ");
                    break;
                }
                //寻找任务马上把它变成准备态
                mDownloadController.updateDownloadTaskState(mDownloadTaskNow, TaskState.TASK_STATE_PREPARE);
            }

            boolean isPrepareOk=doPrepare();


            //如果当前任务准备失败了，那么我们就继续下一个任务
            if (!isPrepareOk) {
                continue;
            }
            //任务准备完成  进行下载 :
            Logger.e("准备成功 ：  "+mDownloadTaskNow.getName());
            //准备成功 更新下载状态
            mDownloadController.updateDownloadTaskState(mDownloadTaskNow, TaskState.TASK_STATE_ING);
            InputStream inputStream = null;
            FileOutputStream fileOutputStream = null;
            HttpURLConnection httpURLConnection = null;
            try {
                URL url = new URL(mDownloadTaskNow.getUrl());
                httpURLConnection = (HttpURLConnection) url.openConnection();
                httpURLConnection.setRequestProperty("Connection","Keep-Alive");
                httpURLConnection.setReadTimeout(10000);
                httpURLConnection.setConnectTimeout(10000);
                //判断是否已经下载过一部分
                if (mDownloadTaskNow.getNowSize()!=0) {
                    File file=new File(mDownloadTaskNow.getSavaPath());
                    if (file.exists()) {
                        fileOutputStream = new FileOutputStream(mDownloadTaskNow.getSavaPath(),true);
                        //"Range","100-1000"   "mDownloadTaskNow.getDownloadSize()-"加 - 是不指明上限
                        // 设置下载的请求范围 在100到1000个字节范围内。
                        httpURLConnection.setRequestProperty("Range", "bytes=" + mDownloadTaskNow.getNowSize()+ "-");
                    }else{
                        fileOutputStream = new FileOutputStream(mDownloadTaskNow.getSavaPath());
                    }

                }else{
                    fileOutputStream = new FileOutputStream(mDownloadTaskNow.getSavaPath());
                }
                inputStream = httpURLConnection.getInputStream();



                byte[] bs = new byte[1024 * 100];
                int total = -1;
                long timeBegin=System.currentTimeMillis();
                int sizeTotal=0;
                while ((total = inputStream.read(bs)) != -1) {
                    //取消任务
                    if (mDownloadController.hasCanceled(mDownloadTaskNow)) {
                        //如果当前任务取消了 ，终止当前任务执行 进入下次任务执行
                        release(inputStream,fileOutputStream,httpURLConnection);

                        //如果任务取消，删除文件
                        File file=new File(mDownloadTaskNow.getSavaPath());
                        file.delete();
                        continue aa;
                    }
                    //暂停任务
                    if (mDownloadController.haspaused(mDownloadTaskNow)) {
                        continue aa;
                    }
                    //计算速度，最快每一秒更新一次下载进度
                    long timeNow=System.currentTimeMillis();
                    sizeTotal+=total;
                    long timeTotal=timeNow-timeBegin;
                    if (timeTotal>=1000) {
                        long speedBytes = (long) (sizeTotal / (timeTotal / 1000.0f));
                        String speed = SizeUtil.formatSpeed(speedBytes);
                        mDownloadController.updateDownloadTaskSpeed(mDownloadTaskNow,speed);
                        //轮换
                        timeBegin=timeNow;
                        sizeTotal=0;
                    }

                    //写数据到本地
                    fileOutputStream.write(bs, 0, total);
                    mDownloadController.updateDownloadTaskSize(mDownloadTaskNow,total);
                }
                //验证sha1，完成任务
                String sha1Origin=mDownloadTaskNow.getSha1();
                if (TextUtils.isEmpty(sha1Origin)) {
                    //！！！！！状态
                    mDownloadController.updateDownloadTaskState(mDownloadTaskNow,TaskState.TASK_STATE_DONE);
                }else{
                    //！！！！！状态
                    mDownloadController.updateDownloadTaskState(mDownloadTaskNow,TaskState.TASK_STATE_SHA1_CHECKING);
                    String sha1Local= MakeFileHash.getFileSHA1(mDownloadTaskNow.getSavaPath());
                    if (sha1Origin.equals(sha1Local)) {
                        mDownloadController.updateDownloadTaskState(mDownloadTaskNow,TaskState.TASK_STATE_DONE);
                    }else{
                        mDownloadController.resetDownSize(mDownloadTaskNow);
                        //！！！！！下载完成，停止验证SHA1  更新状态
                        mDownloadController.updateDownloadTaskState(mDownloadTaskNow, TaskState.TASK_STATE_ERROR_SHA1);
                    }
                }
            } catch (MalformedURLException e) {
                mDownloadController.updateDownloadTaskState(mDownloadTaskNow,TaskState.TASK_STATE_ERROR_NET);
                e.printStackTrace();
            } catch (IOException e) {
                mDownloadController.updateDownloadTaskState(mDownloadTaskNow,TaskState.TASK_STATE_ERROR_NET);
                e.printStackTrace();
            } finally {
                release(inputStream,fileOutputStream,httpURLConnection);
            }
        }

    }


    private boolean doPrepare() {

        boolean isSDK=checkSD();
        if (!isSDK) {
            mDownloadController.updateDownloadTaskState(mDownloadTaskNow,TaskState.TASK_STATE_ERROR_SD);
            return false;
        }
        boolean isURLOK=checkURL();
        if (!isURLOK) {
            mDownloadController.updateDownloadTaskState(mDownloadTaskNow,TaskState.TASK_STATE_ERROR_NET);
            return false;
        }
        return true;
        //return checkSD()&&checkURL();
    }

    private boolean checkURL() {
        DownloadUrlServe downloadUrlServe= NetJsonUtil.getRetrofit(Constant.BASE_URL,DownloadUrlServe.class);
        Call<DownloadUrlEntity> call = downloadUrlServe.request(mDownloadTaskNow.getFid(), CookieUtil.getCookie());
        try {
            Response<DownloadUrlEntity> response = call.execute();

            DownloadUrlEntity downloadUrlEntity = response.body();
            if (downloadUrlEntity.isState()) {
                mDownloadController.updateDownloadTaskUrl(mDownloadTaskNow, downloadUrlEntity.getUrl().replace("http://101.200.183.103",
                        "http://101.200.183.103:9999"));
                return true;
            }else{
                return false;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    private boolean checkSD() {
        synchronized (SYNC){
            int sizeRequire=mDownloadTaskNow.getTotalSize()+mDownloadController.getTotalSizeIngRequire();
            return SDUtil.canUseSDCard(sizeRequire);
        }
    }
    public void release(InputStream inputStream, FileOutputStream fileOutputStream, HttpURLConnection httpURLConnection){
        if (inputStream != null) {
            try {
                inputStream.close();
                inputStream=null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (fileOutputStream != null) {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                    fileOutputStream=null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        if (httpURLConnection != null) {
            httpURLConnection.disconnect();
            httpURLConnection=null;
        }
    }
}
